package com.uduemc.biso.node.web.interceptor;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.uduemc.biso.core.extities.center.Host;
import com.uduemc.biso.core.extities.center.Site;
import com.uduemc.biso.core.extities.center.SysLanguage;
import com.uduemc.biso.node.core.entities.HDomain;
import com.uduemc.biso.node.core.entities.SCodeSite;
import com.uduemc.biso.node.core.entities.SConfig;
import com.uduemc.biso.node.core.entities.SSeoSite;
import com.uduemc.biso.node.web.component.RequestHolder;
import com.uduemc.biso.node.web.component.SiteHolder;
import com.uduemc.biso.node.web.component.SpringContextUtils;
import com.uduemc.biso.node.web.entities.AccessHost;
import com.uduemc.biso.node.web.entities.AccessSite;
import com.uduemc.biso.node.web.exception.NotFoundLanguageException;
import com.uduemc.biso.node.web.exception.NotFoundSiteException;
import com.uduemc.biso.node.web.exception.NotInitSiteException;
import com.uduemc.biso.node.web.exception.PreviewNotDefaultDomainException;
import com.uduemc.biso.node.web.service.VirtualFolderService;
import com.uduemc.biso.node.web.service.byfeign.CodeService;
import com.uduemc.biso.node.web.service.byfeign.LanguageService;
import com.uduemc.biso.node.web.service.byfeign.SeoService;
import com.uduemc.biso.node.web.service.byfeign.SiteConfigService;
import com.uduemc.biso.node.web.service.byfeign.SiteService;

/**
 * 针对域名的拦截器 通过拦截获取域名对应的host、site数据信息，以及是否能够有权限访问的过滤
 * 
 * @author guanyi
 *
 */
@Component
public class SiteInterceptor implements HandlerInterceptor {

	private static final Logger logger = LoggerFactory.getLogger(SiteInterceptor.class);

	@Autowired
	private RequestHolder requestHolder;

	@Autowired
	private SiteHolder siteHolder;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		SiteService siteServiceImpl = SpringContextUtils.getBean("siteServiceImpl", SiteService.class);
		SiteConfigService siteConfigServiceImpl = SpringContextUtils.getBean("siteConfigServiceImpl", SiteConfigService.class);
		LanguageService languageServiceImpl = SpringContextUtils.getBean("languageServiceImpl", LanguageService.class);
		AccessHost accessHost = requestHolder.getAccessHost();
		Host host = accessHost.getHost();
		Long hostId = host.getId();
		String domain = accessHost.getDomain();
		HDomain hDomain = accessHost.getHDomain();

		String uri = accessHost.getUri();
		boolean preview = false;
		// 目前统一为动态页面
//		preview = true;
		if (request.getRequestURI().startsWith("/preview/")) {
			preview = true;
			if (hDomain != null && hDomain.getDomainType() != null && hDomain.getDomainType().shortValue() == (short) 1) {
				// 如果是用户绑定的域名，不允许产生预览状态
				logger.error(domain + " 一定是系统域名才能预览！");
				throw new PreviewNotDefaultDomainException(domain + " 一定是系统域名才能预览！");
			}
			uri = "/" + uri.substring("/preview/".length());
		}

		Site site = null;
		SysLanguage language = null;
		String lanno = "";
		// 通过请求的 uri 确定访问模式、语言以及真正的数据 uri 路径
		if (StringUtils.isEmpty(uri)) {
			// 默认站点
			site = siteServiceImpl.getDefaultSite(hostId);
			if (site == null) {
				// 未能找到site数据
				logger.error("默认站点数据未能找到！ hostId： " + hostId);
				throw new NotFoundSiteException("默认站点数据未能找到！ hostId： " + hostId);
			}
			// 默认语言
			language = languageServiceImpl.getLanguageBySite(site);
			// 默认页面
			uri = "/";
		} else {
			Pattern pattern = Pattern.compile("^(/(\\w{2})/)(.*)");
			Matcher matcher = pattern.matcher(uri);
			if (matcher.find()) {
				// 语言
				lanno = matcher.group(2).toLowerCase();
				// 通过语言简写找到 language
				language = languageServiceImpl.getLanguageByLanno(lanno);
				if (language == null) {
					// 未能找到language数据
					VirtualFolderService virtualFolderServiceImpl = SpringContextUtils.getBean("virtualFolderServiceImpl", VirtualFolderService.class);
					if (virtualFolderServiceImpl.validFileUri(uri)) {
						virtualFolderServiceImpl.responseVirtualFolderFileUri(uri, response);
						return false;
					} else {
						// 否则抛出未能通过后缀获取页面信息的页面内容
						logger.error("通过简写未能找到语言 lanno： " + lanno.toString());
						throw new NotFoundLanguageException("通过简写未能找到语言 lanno： " + lanno.toString());
					}
				}
				site = siteServiceImpl.getSiteByLanguageId(hostId, language.getId());
				uri = "/" + matcher.group(3);
			} else {
				// 默认站点
				site = siteServiceImpl.getDefaultSite(hostId);
				// 默认语言
				language = site == null ? null : languageServiceImpl.getLanguageBySite(site);
			}
		}
		if (site == null) {
			// 未能找到site数据
			logger.error("站点数据未能找到！ hostId： " + hostId);
			throw new NotFoundSiteException("站点数据未能找到！ hostId： " + hostId);
		}
		if (language == null) {
			// 未能找到language数据
			logger.error("站点的语言数据未能找到！ site： " + site.toString());
			throw new NotFoundLanguageException("站点的语言数据未能找到！ site： " + site.toString());
		}

		// 获取 s_config 数据信息
		SConfig sConfig = siteConfigServiceImpl.getInfoBySiteId(hostId, site.getId());
		if (sConfig == null) {
			// 站点未能初始化
			logger.error("未能获取到初始化 SConfig 数据！hostId: " + hostId + " site： " + site.toString());
			throw new NotInitSiteException("未能获取到初始化 SConfig 数据！hostId: " + hostId + " site： " + site.toString());
		}
		Short status = sConfig.getStatus();
		if (status != null && status.shortValue() == 0) {
			logger.error("当前站点的语言被关闭，请进入后台开启！");
			throw new NotFoundSiteException("当前站点的语言被关闭，请进入后台开启！");
		}

		AccessSite accessSite = new AccessSite();
		accessSite.setPreview(preview);
		accessSite.setUri(uri);
		accessSite.setLanno(lanno);
		accessSite.setSite(site);
		accessSite.setSiteConfig(sConfig);
		accessSite.setLanguage(language);

		// 加入 holder
		requestHolder.set(accessSite);

		// host、site 的seo、code数据获取
		SeoService seoServiceImpl = SpringContextUtils.getBean("seoServiceImpl", SeoService.class);
		SSeoSite sSeoSite = seoServiceImpl.getSiteSeoByHostSiteId(hostId, accessSite.getSite().getId());
		siteHolder.setSeoSite(sSeoSite);

		CodeService codeServiceImpl = SpringContextUtils.getBean("codeServiceImpl", CodeService.class);
		SCodeSite sCodeSite = codeServiceImpl.getCodeSiteByHostSiteId(hostId, accessSite.getSite().getId());
		siteHolder.setCodeSite(sCodeSite);

		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
		requestHolder.clean();
	}
}
